JAVA(二)JAVA并发编程

您所在的位置:网站首页 java并发编程艺术 pdf JAVA(二)JAVA并发编程

JAVA(二)JAVA并发编程

2023-12-05 21:59| 来源: 网络整理| 查看: 265

JAVA多线程并发 java多线程实现方法继承thread类实现runnable方法实现Callable方法基于线程池无返回值有返回值 四种线程池newCachedThreadPoolnewFixedThreadPoolnewScheduledThreadPoolnewSingleThreadExecutor 终止线程方式正常运行结束使用退出标志位Interrupt方法结束 sleep和wait区别synchronizedshutdown 和shutdownNow线程池阻塞四种线程池比较

java多线程实现方法 继承thread类 public class MyThread extends Thread { public void run() { // 函数体 System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); myThread1.start();

在主函数中启动子线程start(),子线程会处于就绪状态,看和主线程谁先抢到线程谁再执行,因此最好让主线程sleep一段时间让子线程开始执行。

实现runnable方法 public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } } //启动 MyThread,需要首先实例化一个 Thread,并传入自己的 MyThread 实例: MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start();

实现接口可以不占用仅用的继承

实现Callable方法

Callable方法带有返回值,结合FutureTask获取返回值。

基于线程池 无返回值 // 创建线程池 ExecutorService threadPool = Executors.newFixedThreadPool(10); while(true) { threadPool.execute(new Runnable() { // 提交多个线程任务,并执行 @Override public void run() { System.out.println(Thread.currentThread().getName() + " is running .."); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } 有返回值 class MyCallable implements Callable{ private String s; public MyCallable(String s) { this.s=s; } //实现call方法 @Override public String call() throws Exception { return this.s; } } public static void main(String[] args) throws ExecutionException, InterruptedException { // 使用线程池获取输出 ExecutorService pool = Executors.newFixedThreadPool(1000); // 创建多个有返回值的任务 List list=new ArrayList(); for (int i = 0; i System.out.println("res: "+f.get().toString()); } } 四种线程池 newCachedThreadPool

调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并 从缓存中移除那些已有 60 秒钟未被使用的线程。将空闲线程标记为“空闲”来实现重用。当有新的任务到来时,线程池会优先选择这些空闲线程来执行任务。

newFixedThreadPool

创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。

newScheduledThreadPool

创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

newSingleThreadExecutor

返回一个线程池(这个线程池只有一个线程),这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行。

终止线程方式 正常运行结束 使用退出标志位 public class ThreadSafe extends Thread { public volatile boolean exit = false; public void run() { while (!exit){ //do something } } } Interrupt方法结束

线程处于阻塞状态:如使用了 sleep,同步锁的 wait,socket 中的 receiver,accept 等方法时,会使线程处于阻塞状态。当调用线程的 interrupt()方法时,会抛出 InterruptException 异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后 break 跳出循环状态,从而让 我们有机会结束这个线程的执行。通常很多人认为只要调用 interrupt 方法线程就会结束,实际上是错的, 一定要先捕获InterruptedException 异常之后通过 break 来跳出循环,才能正常结束 run 方法。

public class BlockThreadInterruptTest { public static void main(String[] args) throws InterruptedException { Thread m=new myThread(); Thread.sleep(5000);//一定要让主线程睡,不然start和interrupt谁先执行还不一定呢 m.start(); m.interrupt(); } } class myThread extends Thread{ public void run(){ while (true){ try { Thread.sleep(1000); // 一直处于阻塞状态 } catch (InterruptedException e) { e.printStackTrace(); System.out.println("已退出"); break; } } } }

线程处于未阻塞状态:使用 isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置 true,和使用自定义的标志来控制循环是一样的道理。

public class ThreadSafe extends Thread { public void run() { while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出 try{ Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出 }catch(InterruptedException e){ e.printStackTrace(); break;//捕获到异常之后,执行 break 跳出循环 } } } } sleep和wait区别

sleep方法线程不会释放对象锁。 而调用wait方法线程会放弃对象锁,进入等待锁定池,只有针对此对象调用 notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

synchronized

属于独占式的悲观锁,同时属于可重入锁。 作用范围: 作用于方法,锁住对象实例 作用于静态方法,锁住是Class实例 synchronized 作用于一个对象实例时,锁住的是所有以该对象为锁的代码块

class X { // 方式一:修饰非静态方法 synchronized void foo() { // 临界区 } // 方式二:修饰静态方法 synchronized static void bar() { // 临界区 } // 方式三:修饰代码块 Object obj = new Object(); void baz() { synchronized(obj) { // 临界区 } } } shutdown 和shutdownNow

在调用 shutdown 后,线程池将不再接受新的任务,但会等待已提交的任务执行完毕。因此,在线程任务中设置较长的Thread.sleep()时间会等睡醒再结束。 在调用 shutdownNow 后,用于尝试立即关闭线程池,并停止正在执行的任务。与 shutdown 方法不同,shutdownNow 方法不会等待任务执行完毕,而是尝试中断正在执行的任务,并返回尚未开始执行的任务列表。

线程池阻塞

newFixedPool和newSinglePool、newCachePool均会阻塞主线程,需要在submit之后调用shutdown来关闭线程。

四种线程池比较

newSinglePool只有一个核心线程,当有工作线程时,会提交任务到阻塞队列,从阻塞队列取线程执行,适用于串行化场景。

newFixedPool是固定线程池,线程数量固定,当所有线程处于活动状态时,会将附加任务在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在,适用于控制线程数的场景。

newCachePool是可缓存线程池,线程数量可以根据需要动态增加,当有新任务到来时,如果有空闲线程可用,就会重用它们,如果没有可用线程,则创建新线程。当线程在一段时间内没有被使用,它们会被终止并从线程池中移除,适用于并发量大但执行周期短的场景。

newSheculedExcutor是周期性线程池,周期性是去任务队列拉去任务时,会修改time变量为下次要执行的时间。

可以这么说,线程池内部维护了一个任务队列来存储等待执行的任务;线程池内部维护了线程对象的集合,线程队列包含了已创建和可用的线程。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3